/*
 * BrokerClienteAceptor.cpp
 *
 *  Created on: Jan 28, 2010
 *      Author: jgrande
 */

#include "BrokerCliente.h"

using middleware::common::PDUPuntoAPunto;

void aceptor_sigint_handler(int signal) {
	logger << LogType::LOG_DEBUG_0 << "eliminando procesos creados por el "
			"aceptor" << logger.endl;
	Utiles::registrar_signal(SIGINT, SIG_IGN);
	if(kill(0, SIGINT)==-1) {
		logger << LogType::LOG_ERROR << "Error interrumpiendo procesos "
				"emisores y receptores creados por el proceso aceptor"
				<< logger.err << logger.endl;
	} else {
		pid_t ret;
		while((ret=wait(NULL))!=-1 || errno==EINTR) {
			if(errno!=EINTR) {
				logger << LogType::LOG_DEBUG_0 << "\tterminó el proceso " <<
						ret << logger.endl;
			}
		}
	}
	logger << LogType::LOG_DEBUG_0 << "proceso aceptor terminado" << logger.endl;
	exit(0);
}

void _brokerClienteAceptor();
Direccion handshake(TCPSocket& sock);

pid_t brokerClienteAceptor() {
	pid_t pid;

	if((pid=fork())==0) {
		logger.set_pname("Middleware/Aceptor");
		Utiles::registrar_signal(SIGINT, aceptor_sigint_handler);
		setpgrp();
		_brokerClienteAceptor();
		exit(0);
	}

	return pid;
}

void _brokerClienteAceptor() {
	MiddlewareCliente& mw = MiddlewareClienteSingleton::instance();
	TCPSocket sockserv;
	DireccionTCP dirTCP = ConfigSingleton::instance().getHost(
			ConfigSingleton::instance().getDirLocal());
//	pid_t pidEmisor,
	pid_t pidReceptor;
	Direccion dirRemota;

	sockserv.listen(dirTCP.port, 5);

	forever {
		logger << LogType::LOG_DEBUG_0 << "Esperando conexiones entrantes en puerto "
				<< dirTCP.port << "..." << logger.endl;

		TCPSocket sock = sockserv.accept();
		if(sock) {
			logger << LogType::LOG_DEBUG_0 << "Conexión aceptada!" << logger.endl;

			mw.getLineas().lock();

			if((dirRemota=handshake(sock))!=DIR_INVALIDA) {
				pidReceptor=brokerClienteReceptor(sock);
				if(pidReceptor!=(pid_t)-1) {
					mw.getSem().wait();
				} else {
					logger << LogType::LOG_ERROR << "Error lanzando receptor"
							<< logger.err << logger.endl;
				}
			} else {
				logger << LogType::LOG_ERROR << "Falló el handshake" << logger.endl;
			}

			sock.close();

			mw.getLineas().unlock();
		}
	}
}

Direccion handshake(TCPSocket& sock) {
	Direccion dirLocal = ConfigSingleton::instance().getDirLocal();
	PDUPuntoAPunto pdu = {
			{'P', 'P'}, 							// protocolo
			1, 										// version
			0,										// destino
			dirLocal,								// origen
			middleware::common::OP_HANDSHAKE_REQ,	// operación
			0,										// número de secuencia
			0,										// longitud datos
			{0}										// datos
	};

	logger << LogType::LOG_DEBUG_0 << "Iniciando handshake..." << logger.endl;
	if(!sock.send(&pdu)) {
		logger << LogType::LOG_ERROR <<"error en TCPSocket.send" << logger.err << logger.endl;
		return DIR_INVALIDA;
	}

	logger << LogType::LOG_DEBUG_0 << "Handshake iniciado, esperando respuesta..." << logger.endl;
/*
	if(!sock.recv(&pdu)) {
		logger << LogType::LOG_ERROR << "error en TCPSocket.recv" << logger.err << logger.endl;
		return -1;
	}

	logger << LogType::LOG_DEBUG_0 << "Respuesta recibida." << logger.endl;
	if(pdu.operacion!=middleware::common::OP_HANDSHAKE_RES) {
		logger << LogType::LOG_ERROR <<"Respuesta inválida! (" << pdu.operacion << ")" << logger.endl;
		return -1;
	}

	logger << LogType::LOG_DEBUG_0 <<"Handshake completado con host " << pdu.origen << logger.endl;

	return pdu.origen;
*/
	return 1;
}
